package com.atguigu.guli.service.edu.service.impl;

import com.atguigu.guli.common.base.result.R;
import com.atguigu.guli.service.edu.entity.*;
import com.atguigu.guli.service.edu.entity.form.CourseInfoForm;
import com.atguigu.guli.service.edu.entity.vo.CoursePublishVo;
import com.atguigu.guli.service.edu.entity.vo.CourseQueryVo;
import com.atguigu.guli.service.edu.entity.vo.CourseVo;
import com.atguigu.guli.service.edu.feign.OssFileService;
import com.atguigu.guli.service.edu.mapper.*;
import com.atguigu.guli.service.edu.service.CourseService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;

/**
 * <p>
 * 课程 服务实现类
 * </p>
 *
 * @author Helen
 * @since 2020-04-01
 */
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements CourseService {

    // 注意：为了避免idea在这个位置报告找不到依赖的错误，
    // 我们可以在CourseDescriptionMapper接口上添加@Repository注解
    @Autowired
    private CourseDescriptionMapper courseDescriptionMapper;

    @Autowired
    private VideoMapper videoMapper;
    @Autowired
    private ChapterMapper chapterMapper;
    @Autowired
    private CommentMapper commentMapper;
    @Autowired
    private CourseCollectMapper courseCollectMapper;

    @Autowired
    private OssFileService ossFileService;

    /**
     * 功能描述：保存课程和课程详情信息
     *
     * @param courseInfoForm 前端传过来的课程表单
     * @return String 新生成的课程id
     * @author cakin
     * @date 2020/12/5
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String saveCourseInfo(CourseInfoForm courseInfoForm) {
        // 保存课程基本信息
        Course course = new Course();
        BeanUtils.copyProperties(courseInfoForm, course);
        course.setStatus(Course.COURSE_DRAFT);
        baseMapper.insert(course);

        // 保存课程详情信息
        CourseDescription courseDescription = new CourseDescription();
        courseDescription.setDescription(courseInfoForm.getDescription());
        courseDescription.setId(course.getId());
        courseDescriptionMapper.insert(courseDescription);
        return course.getId();
    }

    /**
     * 功能描述：根据id获得课程信息
     *
     * @param id 课程id
     * @return CourseInfoForm 课程详情
     * @author cakin
     * @date 2020/12/5
     */
    @Override
    public CourseInfoForm getCourseInfoById(String id) {
        // 根据id获取Course
        Course course = baseMapper.selectById(id);
        if (course == null) {
            return null;
        }
        // 根据id获取CourseDescription
        CourseDescription courseDescription = courseDescriptionMapper.selectById(id);
        // 组装成CourseInfoForm
        CourseInfoForm courseInfoForm = new CourseInfoForm();
        BeanUtils.copyProperties(course, courseInfoForm);
        courseInfoForm.setDescription(courseDescription.getDescription());
        return courseInfoForm;
    }

    /**
     * 功能描述：更新课程和课程详情信息
     *
     * @param courseInfoForm 前端传过来的课程表单
     * @return String 新生成的课程id
     * @author cakin
     * @date 2020/12/5
     */
    @Override
    public void updateCourseInfoById(CourseInfoForm courseInfoForm) {
        // 更新Course
        Course course = new Course();
        BeanUtils.copyProperties(courseInfoForm, course);
        baseMapper.updateById(course);
        // 更新CourseDescription
        CourseDescription courseDescription = new CourseDescription();
        courseDescription.setDescription(courseInfoForm.getDescription());
        courseDescription.setId(courseInfoForm.getId());
        courseDescriptionMapper.updateById(courseDescription);
    }

    /**
     * 功能描述：查询课程列表
     *
     * @param page          页码
     * @param limit         每页记录数
     * @param courseQueryVo 查询条件
     * @return IPage<CourseVo> 返回分页
     * @author cakin
     * @date 2020/12/6
     */
    @Override
    public IPage<CourseVo> selectPage(Long page, Long limit, CourseQueryVo courseQueryVo) {
        // 组装查询条件
        QueryWrapper<CourseVo> queryWrapper = new QueryWrapper<>();
        // 按照创建时间降序排列
        queryWrapper.orderByDesc("c.gmt_create");
        // 获取查询条件
        String title = courseQueryVo.getTitle();
        String teacherId = courseQueryVo.getTeacherId();
        String subjectParentId = courseQueryVo.getSubjectParentId();
        String subjectId = courseQueryVo.getSubjectId();
        // 标题
        if (!StringUtils.isEmpty(title)) {
            queryWrapper.like("c.title", title);
        }
        // 讲师id
        if (!StringUtils.isEmpty(teacherId)) {
            queryWrapper.eq("c.teacher_id", teacherId);
        }
        // 一级分类id
        if (!StringUtils.isEmpty(subjectParentId)) {
            queryWrapper.eq("c.subject_parent_id", subjectParentId);
        }
        // 二级分类id
        if (!StringUtils.isEmpty(subjectId)) {
            queryWrapper.eq("c.subject_id", subjectId);
        }
        // 组装分页
        Page<CourseVo> pageParam = new Page<>(page, limit);
        // 执行分页查询
        // 只需要在mapper层传入封装好的分页组件即可，sql分页条件组装的过程由mp自动完成
        List<CourseVo> records = baseMapper.selectPageByCourseQueryVo(pageParam, queryWrapper);
        // 将records设置到pageParam中
        return pageParam.setRecords(records);
    }

    /**
     * 功能描述：删除课程封面
     *
     * @param id 课程id
     * @return boolean 是否删除成功
     * @author cakin
     * @date 2020/12/6
     */
    @Override
    public boolean removeCoverById(String id) {
        // 根据id获取课程 Cover 的 url
        Course course = baseMapper.selectById(id);
        if (course != null) {
            String cover = course.getCover();
            if (!StringUtils.isEmpty(cover)) {
                R r = ossFileService.removeFile(cover);
                return r.getSuccess();
            }
        }
        return false;
    }

    /**
     * 功能描述：删除课程
     *
     * @param id 课程id
     * @return boolean 是否删除成功
     * 数据库中外键约束的设置：
     * 互联网分布式项目中不允许使用外键与级联更新，一切涉及级联的操作不要依赖数据库层，要在业务层解决
     * 如果业务层解决级联删除功能
     * 那么先删除子表数据，再删除父表数据
     * @author cakin
     * @date 2020/12/6
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean removeCourseById(String id) {
        // 根据 courseId 删除 Video(课时)
        QueryWrapper<Video> videoQueryWrapper = new QueryWrapper<>();
        videoQueryWrapper.eq("course_id", id);
        videoMapper.delete(videoQueryWrapper);
        // 根据 courseId 删除 Chapter(章节)
        QueryWrapper<Chapter> chapterQueryWrapper = new QueryWrapper<>();
        chapterQueryWrapper.eq("course_id", id);
        chapterMapper.delete(chapterQueryWrapper);
        // 根据 courseId 删除 Comment(评论)
        QueryWrapper<Comment> commentQueryWrapper = new QueryWrapper<>();
        commentQueryWrapper.eq("course_id", id);
        commentMapper.delete(commentQueryWrapper);
        // 根据 courseId 删除 CourseCollect(课程收藏)
        QueryWrapper<CourseCollect> courseCollectQueryWrapper = new QueryWrapper<>();
        courseCollectQueryWrapper.eq("course_id", id);
        courseCollectMapper.delete(courseCollectQueryWrapper);
        // 根据 courseId 删除 CourseDescription(课程详情)
        courseDescriptionMapper.deleteById(id);
        // 删除课程
        return this.removeById(id);
    }

    /**
     * 功能描述：根据ID获取课程发布信息
     *
     * @param id 课程id
     * @return CoursePublishVo 课程信息
     * @author cakin
     * @date 2020/12/6
     */
    @Override
    public CoursePublishVo getCoursePublishVoById(String id) {
        return baseMapper.selectCoursePublishVoById(id);
    }
    /**
     * 功能描述：根据id发布课程
     *
     * @param id 课程id
     * @return boolean 是否发布成功
     * @author cakin
     * @date 2020/12/6
     */
    @Override
    public boolean publishCourseById(String id) {
        Course course = new Course();
        course.setId(id);
        course.setStatus(Course.COURSE_NORMAL);
        return this.updateById(course);
    }
}
